package org.ala.tree.lsm.memtable;

import java.io.IOException;
import java.nio.file.Path;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;

import org.ala.tree.lsm.IMemTable;
import org.ala.tree.lsm.LSMConfig;
import org.ala.tree.lsm.tools.FileTools;
import org.ala.tree.lsm.wal.Wal;

/**
 *
 * @author ala
 * @date 2025年5月26日
 */
public abstract class AbstractMemTable<V> implements IMemTable<V> {

	
	/**
	 * 	当前的内存块id
	 */
	protected String id;
	/**
	 * 	当前的wal
	 */
	protected Wal wal;
	/**
	 * 只读标记
	 */
	protected boolean readOnly = false;
	/**
	 * size
	 */
	protected int size;
	/**
	 * 	配置
	 */
	protected LSMConfig config;
	
	public AbstractMemTable(LSMConfig config, String id, boolean isWal) {
		this.id = id;
		this.size = 0;
		this.config = config;
		
		//	初始化wal
		if (isWal) {wal = new Wal(config, id);}
	}
	
	@Override
	public String id() {
		return id;
	}
	
	@Override
	public final boolean put(String k, V v) {
		if (readOnly) {return false;}
		
		int type = MemTableOpEnums.ADD.getVal();
		if (get(k) != null) {
			type = MemTableOpEnums.UPD.getVal();
		}
		
		if (wal == null) {
			doPut(k, v);
			return true;
		}
		
		CompletableFuture<Boolean> cf = wal.write(type, k, v);
		try {
			if (cf.get() && doPut(k, v)) {
				size++;
				return true;
			}
		} catch (InterruptedException | ExecutionException e) {
		}
		return false;
	}
	public abstract boolean doPut(String k, V v);

	
	@Override
	public final V remove(String k) {
		if (readOnly) {return null;}
		V v = get(k);
		if (v == null) {return null;}
		
		if (wal == null) {
			doRemove(k);
			return v;
		}
		
		CompletableFuture<Boolean> cf = wal.write(MemTableOpEnums.DEL.getVal(), k, v);
		try {
			if (cf.get() && doRemove(k)) {
				size--;
				return v;
			}
		} catch (InterruptedException | ExecutionException e) {
		}
		return null;
	}
	public abstract boolean doRemove(String k);
	
	
	@Override
	public int size() {
		return size;
	}
	
	@Override
	public final void setReadOnly() {
		if (wal != null) {wal.close();}
		doSetReadOnly();
		readOnly = true;
	}
	protected void doSetReadOnly() {}

	@Override
	public boolean readOnly() {
		return readOnly;
	}

	@Override
	public void clearWal() {
		//	只有只读的可以删
//		if (!readOnly) {return ;}
		String dir = String.format("%s/%s/%s", config.ROOT_DIR, config.WAL_DIR, id);
		try {
			List<Path> files = FileTools.filesAll(dir, "wal");
			files.forEach(p -> {
				String ap = p.toFile().getAbsolutePath();
				FileTools.fileDel(ap);
			});
			FileTools.fileDel(dir);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	
	
}
